package net.sf.fmj.ui.wizards;

import java.io.IOException;
import java.util.logging.Logger;

import javax.media.DataSink;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoDataSinkException;
import javax.media.NoProcessorException;
import javax.media.NotRealizedError;
import javax.media.Processor;
import javax.media.control.TrackControl;
import javax.media.protocol.DataSource;

import net.sf.fmj.ejmf.toolkit.util.StateWaiter;
import net.sf.fmj.utility.LoggerSingleton;

/**
 * 
 * @author Ken Larson
 * 
 */
public class ProcessorWizardResult {
	private static final Logger logger = LoggerSingleton.logger;

	public Processor processor;
	private StateWaiter stateWaiter;
	private DataSource destDataSource;
	private DataSink destDataSink;

	/** config.url must be set */
	public void step1_createProcessorAndSetUrl(ProcessorWizardConfig config)
			throws WizardStepException {
		String url = config.url;

		if (url == null || url.equals("")) {
			throw new WizardStepException("Source URL may not be blank");

		}

		logger.fine("Creating processor");
		try {
			processor = Manager.createProcessor(new MediaLocator(url));
		} catch (IOException e) {
			throw new WizardStepException(e);

		} catch (NoProcessorException e) {
			throw new WizardStepException(e);
		}

		logger.fine("Created processor " + processor);

		logger.fine("Configuring processor");

		// configure the processor
		stateWaiter = new StateWaiter(processor);
		if (!stateWaiter.blockingConfigure()) {
			throw new WizardStepException("Failed to configure processor");

		}

		logger.fine("Configured processor");
	}

	/** config.contentDescriptor must be set */
	public void step2_setContentDescriptor(ProcessorWizardConfig config)
			throws WizardStepException {
		if (processor.setContentDescriptor(config.contentDescriptor) == null) {
			throw new WizardStepException(
					"Unable to set content descriptor to "
							+ config.contentDescriptor);
		}

	}

	/** config.trackConfigs must be set */
	public void step3_setTrackConfigs(ProcessorWizardConfig config)
			throws WizardStepException {
		TrackConfig[] trackConfigs = config.trackConfigs;

		// forward transition
		final TrackControl trackControls[] = processor.getTrackControls();

		for (int i = 0; i < trackControls.length; i++) {
			final boolean enabled = trackConfigs[i].enabled;
			trackControls[i].setEnabled(enabled);

			if (enabled) { // TODO: do the conversion to Format here, so we can
							// validate.
				Format f = trackConfigs[i].format;
				Format result = trackControls[i].setFormat(f);
				if (result == null) {
					throw new WizardStepException(
							"Unable to set format of track " + i + " to " + f);

				}
			}
		}
	}

	/** config.desturl must be set */
	public void step4_setDestUrlAndStart(ProcessorWizardConfig config)
			throws WizardStepException {
		// ParsedRTPUrl destUrl = config.destUrl;

		if (!stateWaiter.blockingRealize()) {
			throw new WizardStepException("Failed to realize processor");
		}

		try {
			destDataSource = processor.getDataOutput();
		} catch (NotRealizedError e) {
			throw new WizardStepException(e);

		}

		// hand this datasource to manager for creating an RTP
		// datasink our RTP datasink will multicast the audio
		try {
			String url = config.destUrl;

			logger.fine("Dest url: " + url);

			MediaLocator m = new MediaLocator(url);

			destDataSink = Manager.createDataSink(destDataSource, m);
			destDataSink.open();
			destDataSink.start();

			// doesn't appear to do anything:
			// processor.addControllerListener(new ControllerListener() {
			//
			// public void controllerUpdate(ControllerEvent event)
			// {
			// if (event instanceof ControllerClosedEvent)
			// {
			// System.out.println("Controller closed, closing data sink");
			// destDataSink.close();
			//						
			// }
			// }
			//				
			// });

			logger.fine("Starting processor");
			stateWaiter.blockingStart();

		} catch (IOException e) {
			throw new WizardStepException(e);
		} catch (NoDataSinkException e) {
			throw new WizardStepException(e);
		}
	}
}
